/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package weixin.channel.service.impl;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.logging.Level;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import sdk.weinxin.aes.AesException;
import sdk.weinxin.aes.WXBizMsgCrypt;
import static sdk.weinxin.beans.message.MsgType;
import sdk.weinxin.beans.message.XmlMessage;
import sdk.weinxin.beans.message.in.event.Event;
import sdk.weinxin.format.XmlObjectMapper;
import sdk.weinxin.util.DuplicatedMessageChecker;
import weixin.channel.service.MessageGateway;
import weixin.channel.service.TokenService;

/**
 *
 * @author 张森
 */
@Service
public class MessageGatewayImpl implements MessageGateway {

    private static final Logger logger = LoggerFactory.getLogger(MessageGatewayImpl.class);

    @Autowired
    private TokenService tokenService;
    @Autowired
    private DuplicatedMessageChecker duplicatedMessageChecker;
    
    private static final String AES = "aes";

    private String appId;
    private String acToken;
    private String encodingToken;
    private String encodingAesKey;

    @Override
    public String service(
            String signature,
            String msgSignature,
            String timestamp,
            String nonce,
            String echostr,
            String encryptType,
            String context) {
        WXBizMsgCrypt wxBizMsgCrypt = null;
        //加密方式
        boolean isAes = AES.equals(encryptType);
        if (isAes) {
            try {
                wxBizMsgCrypt = new WXBizMsgCrypt(encodingToken, encodingAesKey, appId);
            } catch (AesException e) {
                logger.error("创建解密对象错误", e);
            }
        }
        //首次请求申请验证,返回echostr
        if (isAes && echostr != null) {
            try {
                echostr = URLDecoder.decode(echostr, "utf-8");
                String echostrDecrypt = wxBizMsgCrypt.verifyUrl(msgSignature, timestamp, nonce, echostr);
                return echostrDecrypt;
            } catch (AesException e) {
                logger.error("解密 echostr 异常", e);
            } catch (UnsupportedEncodingException ex) {
                logger.error("解析 echostr 异常", ex);
            }
        } else {
            return echostr;
        }

        try {
            //解密XML 数据
            String xmlData = wxBizMsgCrypt.decryptMsg(msgSignature, timestamp, nonce, context);
            XmlMessage xmlMessage = XmlObjectMapper.defaultMapper().fromXml(xmlData, XmlMessage.class);
            XmlMessageHeader xmlResponse = mpDispatch(xmlRequest);
        } catch (AesException ex) {
            logger.error("解密 消息内容 异常", ex);
        } catch (IOException ex) {
            logger.error("消息内容 传化对象 异常", ex);
        }
    }
    private XmlMessage mpDispatch(XmlMessage xmlRequest) {
        if(!duplicatedMessageChecker.isDuplicated(xmlRequest.getFromUser() + xmlRequest.getCreateTime().getTime())) {
            String welcome = "您好:" + Users.defaultUsers().get(xmlRequest.getFromUser()).getNickName();
            CareMessages.defaultCareMessages().text(xmlRequest.getFromUser(), welcome);

            if (xmlRequest instanceof EventRequest) {
                EventRequest eventRequest = (EventRequest) xmlRequest;
                logger.debug("事件请求[{}]", eventRequest.getEventType().name());
                CareMessages.defaultCareMessages().text(xmlRequest.getFromUser(), "事件请求:" + eventRequest.getEventType().name());
            } else {
                logger.debug("消息请求[{}]", xmlRequest.getMsgType().name());
                CareMessages.defaultCareMessages().text(xmlRequest.getFromUser(), "消息请求:" + xmlRequest.getMsgType().name());
            }
        } else {
            logger.warn("Duplicated message: {} @ {}", xmlRequest.getMsgType(), xmlRequest.getFromUser());
        }

        //需要同步返回消息（被动回复）给用户则构造一个XmlMessageHeader类型，比较鸡肋，因为处理逻辑如果比较复杂响应太慢会影响用户感知，建议直接返回null；
        //要发送消息给用户可以参考上面的例子使用客服消息接口进行异步发送
        return null;
    }
}
